# 通过21关键点实现手势识别
import math
import numpy as np


def get_gesture_garbage(pts_hand):
    label_hand = get_angle(pts_hand)
    if label_hand[1, 1] < 100 or label_hand[1, 2] < 100 or label_hand[1, 0] < 100:
        return 0
    else:
        return 1


def get_angle(pts_hand):
    """
    获得当前手部的各个关节角度
    :param pts_hand: 21关键点
    :return: 手部各个关节角度
    """
    label_hand = np.empty([5, 3], dtype=int)
    for i in range(5):
        v1 = {}
        v2 = {}
        v1['x'] = pts_hand['0']['x'] - pts_hand[str(i * 4 + 1)]['x']
        v1['y'] = pts_hand['0']['y'] - pts_hand[str(i * 4 + 1)]['y']
        v2['x'] = pts_hand[str(i * 4 + 2)]['x'] - pts_hand[str(i * 4 + 1)]['x']
        v2['y'] = pts_hand[str(i * 4 + 2)]['y'] - pts_hand[str(i * 4 + 1)]['y']
        label_hand[i, 0] = angle(v1, v2)
        v3 = {}
        v4 = {}
        v3['x'] = pts_hand[str(i * 4 + 1)]['x'] - pts_hand[str(i * 4 + 2)]['x']
        v3['y'] = pts_hand[str(i * 4 + 1)]['y'] - pts_hand[str(i * 4 + 2)]['y']
        v4['x'] = pts_hand[str(i * 4 + 3)]['x'] - pts_hand[str(i * 4 + 2)]['x']
        v4['y'] = pts_hand[str(i * 4 + 3)]['y'] - pts_hand[str(i * 4 + 2)]['y']
        label_hand[i, 1] = angle(v3, v4)
        v5 = {}
        v6 = {}
        v5['x'] = pts_hand[str(i * 4 + 2)]['x'] - pts_hand[str(i * 4 + 3)]['x']
        v5['y'] = pts_hand[str(i * 4 + 2)]['y'] - pts_hand[str(i * 4 + 3)]['y']
        v6['x'] = pts_hand[str(i * 4 + 4)]['x'] - pts_hand[str(i * 4 + 3)]['x']
        v6['y'] = pts_hand[str(i * 4 + 4)]['y'] - pts_hand[str(i * 4 + 3)]['y']
        label_hand[i, 2] = angle(v3, v4)
    return label_hand


def is_open(finger_angle):
    """
    手指是否张开
    :param finger_angle:
    :return: True or False
    """
    # if finger_angle[0] > 170 and finger_angle[1] > 170 and finger_angle[2] > 170:
    if finger_angle[1] > 170 and finger_angle[2] > 170:
        return True
    return False


def not_open(finger_angle):
    """
    手指是否闭合
    :param finger_angle: 每个手指的三个关节处的角度
    :return: True or False
    """
    if not is_open(finger_angle):
        return True
    return False


def is_curve(finger_angle):
    """
    手指是否弯曲
    :param finger_angle: 每个手指的三个关节处的角度
    :return: True or False
    """
    if 100 <= finger_angle[0] <= 170 and 100 <= finger_angle[1] <= 170 and 100 <= finger_angle[2] <= 170:
        return True
    return False


def get_gesture_control(pts_hand):
    """
    检测21关键点对应的手势，由于每个人在做一些特别的手势
    时大拇指并不一定在同样的位置，因此忽略大拇指的状态(hand_angle[0]),
    目前有4个手势，第零个是没有匹配手势，第一个是喜欢音乐(V)，第二个是切换手势（五指伸开），第三个是播放/暂停（握拳），第四个是音量控制(C)
    :param pts_hand: 手部21关键点
    :return: 当前手部手势
    """
    gesture = 0
    hand_angle = get_angle(pts_hand).tolist()
    if (not is_open(hand_angle[4])) and (not is_open(hand_angle[3])) and is_open(hand_angle[2]) and \
            is_open(hand_angle[1]):
        gesture = 1
    if is_open(hand_angle[4]) and is_open(hand_angle[3]) and is_open(hand_angle[2]) and \
            is_open(hand_angle[1]):
        gesture = 2
    if not_open(hand_angle[4]) and not_open(hand_angle[3]) and not_open(hand_angle[2]) and \
            not_open(hand_angle[1]):
        gesture = 3
    if not_open(hand_angle[4]) and not_open(hand_angle[3]) and not_open(hand_angle[2]) and \
            is_curve(hand_angle[1]):
        gesture = 4

    return gesture


def angle(v1, v2):
    """
    获得两向量间角度
    :param v1: 向量1
    :param v2: 向量2
    :return: 两向量间角度
    """
    dx1 = v1['x']
    dy1 = v1['y']
    dx2 = v2['x']
    dy2 = v2['y']
    angle1 = math.atan2(dy1, dx1)
    angle1 = int(angle1 * 180 / math.pi)
    angle2 = math.atan2(dy2, dx2)
    angle2 = int(angle2 * 180 / math.pi)
    if angle1 * angle2 >= 0:
        included_angle = abs(angle1 - angle2)
    else:
        included_angle = abs(angle1) + abs(angle2)
        if included_angle > 180:
            included_angle = 360 - included_angle
    return included_angle
